package com.tt.vtg.utils;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ZooKeeperImportUtil {
	private static final String SEPARATOR = "/";
	private ZooKeeper zk = null;
	private ZooKeeperImportUtil(){try {
		cfg = parse();
		String zkHosts = cfg.getConnects();
		zk = new ZooKeeper(zkHosts, 30000, (e)->{});
	} catch (Exception e) {
		e.printStackTrace();
	}}
	private Cfg cfg;
    private static ObjectMapper om = new ObjectMapper();
    public static ZooKeeperImportUtil getInstance(){
        return ZooKeeperImportUtilSingleton.INSTANCE.get();
    }
    private Cfg parse()throws JsonParseException, JsonMappingException, IOException{
        return om.readValue(ClassLoader.getSystemClassLoader().getResourceAsStream("zkImport.json"), Cfg.class);
    }
    
    public void importZKData() throws Exception{
    	cfg.getProfiles().stream().forEach(p->{
    		createNode(SEPARATOR + p.getRoot(), "");
    		String ctx = SEPARATOR + p.getRoot() + SEPARATOR + p.getContext() + p.getSeparator() + p.getProfile();
    		createNode(ctx, "");
    		
    		p.getValues().forEach((k, v) ->{
    			createNode(ctx+SEPARATOR+k, v);
    		});
    	});
    	
    	zk.close();
    }
    
    private void createNode(String path, String value){
    	if(!nodeExist(path)){
			try {
				zk.create(path, value.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
				System.out.println("create " + path + " with value: " + value);
			} catch (Exception e) {
				e.printStackTrace();
			} 
		}
    }
    
    private boolean nodeExist(String path){
    	try {
			return zk.exists(path, false)==null ? false : true;
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	return true;
    }
    public static void main(String[] args)  {
        try {
        	ZooKeeperImportUtil.getInstance().importZKData();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    enum ZooKeeperImportUtilSingleton{
        INSTANCE;
        private ZooKeeperImportUtil ins;
        ZooKeeperImportUtilSingleton(){
            ins = new ZooKeeperImportUtil();
        }
        public ZooKeeperImportUtil get(){
            return ins;
        }
    }
    static class Cfg{
        @JsonProperty("profiles")
        List<Profiles> profiles;
        @JsonProperty("zkConns")
        private String connects;
        public String getConnects() {
            return connects;
        }
        void setConnects(String connects) {
            this.connects = connects;
        }
        public List<Profiles> getProfiles() {
			return profiles;
		}
		public void setProfiles(List<Profiles> profiles) {
			this.profiles = profiles;
		}

		static class Profiles{
            @JsonProperty("context")
            private String context;
            @JsonProperty("root")
            private String root;
            @JsonProperty("profile")
            private String profile;
            @JsonProperty("separator")
            private String separator;
            @JsonProperty("values")
            Map<String, String> values;
            
            public Map<String, String> getValues() {
                return values;
            }
            void setValues(Map<String, String> values) {
                this.values = values;
            }
            public String getContext() {
                return context;
            }
            void setContext(String context) {
                this.context = context;
            }
            public String getRoot() {
                return root;
            }
            void setRoot(String root) {
                this.root = root;
            }
            public String getProfile() {
                return profile;
            }
            void setProfile(String profile) {
                this.profile = profile;
            }
            public String getSeparator() {
                return separator;
            }
            void setSeparator(String separator) {
                this.separator = separator;
            }
        }
    }
}

